package com.randb.easyhttp.func;

import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.randb.easyhttp.model.ApiResult;
import com.randb.easyhttp.utils.Utils;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import io.reactivex.functions.Function;
import okhttp3.ResponseBody;

/**
 * User: RandBII
 * Date: 2020/5/27
 * Description:
 */
public class ApiResultFunc<T> implements Function<ResponseBody, ApiResult<T>> {

    protected Type type;
    protected Gson gson;

    public ApiResultFunc(Type type) {
        this.type = type;
        gson = new GsonBuilder()
                .excludeFieldsWithModifiers(Modifier.FINAL, Modifier.TRANSIENT, Modifier.STATIC)
                .serializeNulls()
                .create();
    }


    @Override
    public ApiResult<T> apply(ResponseBody responseBody) throws Exception {

        ApiResult<T> apiResult = new ApiResult<>();
        apiResult.setCode(-1);

        if (type instanceof ParameterizedType) { // 泛型
            final Class<T> cls = (Class) ((ParameterizedType) type).getRawType();
            if (ApiResult.class.isAssignableFrom(cls)) { // 1. 相同的类 2.是 cls 直接或者间接父类，或者接口的直接或者间接父类
                final Type[] params = ((ParameterizedType) type).getActualTypeArguments();
                final Class clazz = Utils.getClass(params[0], 0);
                final Class rawType = Utils.getClass(type, 0);
                try {
                    String json = responseBody.string();
                    if (!List.class.isAssignableFrom(rawType) && clazz.equals(String.class)) {
                        apiResult.setData((T) json);
                        apiResult.setCode(0);
                    } else {
                        ApiResult result = gson.fromJson(json, type);
                        if (result != null) {
                            apiResult = result;
                        } else {
                            apiResult.setMessage("json is null");
                        }
                    }
                } catch (Exception e) {
                    apiResult.setMessage(e.getMessage());
                    e.printStackTrace();
                } finally {
                    responseBody.close();
                }
            } else {
                apiResult.setMessage("ApiResult.class.isAssignableFrom(cls) is error ");
            }
        } else { //   默认的ApiResult;
            try {
                final String json = responseBody.string();
                final Class<T> clazz = Utils.getClass(type, 0);
                if (clazz.equals(String.class)) {
                    final ApiResult result = parseApiResult(json, apiResult);
                    if (result != null) {
                        apiResult = result;
                        apiResult.setData((T) json);
                    } else {
                        apiResult.setMessage("json is null ");
                    }
                } else {
                    final ApiResult result = parseApiResult(json, apiResult);

                    if (result != null) {
                        apiResult = result;
                        if (apiResult.getData() != null) {
                            T data = gson.fromJson(apiResult.getData().toString(), clazz);
                            apiResult.setData(data);
                        } else {
                            apiResult.setMessage("data is null");
                        }

                    } else {
                        apiResult.setMessage("json is null ");
                    }
                }
            } catch (Exception e) {
                apiResult.setMessage(e.getMessage());
                e.printStackTrace();
            } finally {
                responseBody.close();
            }

        }


        return apiResult;
    }

    private ApiResult parseApiResult(String json, ApiResult<T> apiResult) throws JSONException {

        if (TextUtils.isEmpty(json)) return null;
        JSONObject jsonObject = new JSONObject(json);
        if (jsonObject.has("code")) {
            apiResult.setCode(jsonObject.getInt("code"));
        }
        if (jsonObject.has("data")) {
            apiResult.setData((T) jsonObject.getString("data"));
        }
        if (jsonObject.has("msg")) {
            apiResult.setMessage(jsonObject.getString("msg"));
        }
        return apiResult;
    }


}
